Unit BRequestHandlerUnit;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils, syncobjs, BRequestUnit, BCustomSessionUnit;

Type

{ BRequestHandlerClass }

 BRequestHandlerClass = Class(TThread)
  Private
    bSection: TCriticalSection;
    bEvent: TEvent;
    bRequest: BRequestClass;
    bHandled: Boolean;
    bSessionsManager: BSessionsManagerClass;
    Procedure Execute; override;
    Procedure HandleRequest;
  Public
    Function IsFree: Boolean;
    Function SetFree: Boolean;
    Function TryHandle(Const aRequest: BRequestClass): Boolean;
    Constructor Build(Const aIndex: Integer;
      Const aProtoSession: BCustomSessionClass);
    Destructor Burn;
End;

Implementation

{ BRequestHandlerClass }

Procedure BRequestHandlerClass.Execute;
Begin
  Repeat
    bSection.Enter;
    If bRequest = nil Then
      Begin
        bEvent.ResetEvent;
        bSection.Leave;
        bEvent.WaitFor(100000);
      End
    Else
      Begin
        bSection.Leave;
        HandleRequest;
      End;
  Until Terminated;
End;

Procedure BRequestHandlerClass.HandleRequest;
Begin
  bSection.Enter;
  bSessionsManager.ProcessRequest(bRequest);
  bRequest.Send;
  bRequest.Burn;
  bRequest := nil;
  bHandled := TRUE;
  bSection.Leave;
End;

Function BRequestHandlerClass.IsFree: Boolean;
Begin
  bSection.Enter;
  Result := bRequest = nil;
  bSection.Leave;
End;

Function BRequestHandlerClass.SetFree: Boolean;
Begin
  Result := FALSE;
  If IsFree Then Exit(TRUE);
  bSection.Enter;
  Result := bHandled;
  If Result Then bRequest := nil;
  bSection.Leave;
End;

Function BRequestHandlerClass.TryHandle(
  Const aRequest: BRequestClass): Boolean;
Begin
  Result := FALSE;
  Try
    bSection.Enter;
    If Not(bHandled) Then Exit;
    If bRequest = nil Then
      Begin
        bRequest := aRequest;
        Result := TRUE;
        bHandled := FALSE;
        bEvent.SetEvent;
      End;
  Finally
    bSection.Leave;
  End;
End;

Constructor BRequestHandlerClass.Build(Const aIndex: Integer;
  Const aProtoSession: BCustomSessionClass);
Begin
  bEvent:=TEvent.Create(nil, TRUE, TRUE, Format('RequestHandler%d', [aIndex]));
  bSection := TCriticalSection.Create;
  bHandled := TRUE;
  bSessionsManager := BSessionsManagerClass.Build(aProtoSession);
  Inherited Create(FALSE);
End;

Destructor BRequestHandlerClass.Burn;
Begin
  bSessionsManager.Burn;
  bSection.Free;
  bEvent.Free;
  Inherited Free;
End;

End.

